using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebTools.UI.WebControls
{
	/// <summary>
	/// Represents the style for a WebTools.UI.WebControls.Alert control.
	/// </summary>
	[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	public sealed class AlertStyle : Style, IStateManager
	{
		private const int PROP_HPADDING = 0;
		private const int PROP_VPADDING = 1;
		private const int PROP_HALIGN = 2;

		private BitArray _bits = new BitArray(3);
		private bool _marked;

		#region Constructor
		/// <summary>
		/// Initializes a new instance of the WebTools.UI.WebControls.AlertStyle class.
		/// </summary>
		public AlertStyle() : this(null)
		{
			this.Initialize();
		}

		/// <summary>
		/// Initializes a new instance of the WebTools.UI.WebControls.AlertStyle class.
		/// </summary>
		/// <param name="bag">A System.Web.UI.StateBag object that represents the state bag in which to store style information.</param>
		public AlertStyle(StateBag bag)
			: base(bag)
		{
			this.Initialize();
		}
		#endregion

		#region Initialize
		private void Initialize()
		{
			_bits.SetAll(false);
		}
		#endregion

		#region Private Methods
		internal bool IsPropSet(int index)
		{
			return _bits.Get(index);
		}
		internal void SetProp(int index)
		{
			_bits.Set(index, true);
		}
		internal void ClearProp(int index)
		{
			_bits.Set(index, false);
		}
		#endregion

		#region Overridden Methods
		/// <summary>
		/// Adds the specified object's style properties to a System.Web.UI.CssStyleCollection object.
		/// </summary>
		/// <param name="attributes">The System.Web.UI.CssStyleCollection object to which to add the style properties.</param>
		/// <param name="urlResolver">A System.Web.UI.IUrlResolutionService -implemented object that contains the 
		/// context information for the current location (URL).</param>
		protected override void FillStyleAttributes(CssStyleCollection attributes, IUrlResolutionService urlResolver)
		{
			base.FillStyleAttributes(attributes, urlResolver);

			if (!this.HorizontalPadding.IsEmpty || !this.VerticalPadding.IsEmpty)
			{
				attributes.Add(HtmlTextWriterStyle.Padding, String.Format(CultureInfo.InvariantCulture, "{0} {1} {0} {1}", new object[] { this.VerticalPadding.IsEmpty ? Unit.Pixel(0) : this.VerticalPadding, this.HorizontalPadding.IsEmpty ? Unit.Pixel(0) : this.HorizontalPadding }));
			}

			if (this.HorizontalAlign != HorizontalAlign.NotSet)
			{
				attributes.Add(HtmlTextWriterStyle.TextAlign, this.HorizontalAlign.ToString().ToLower(CultureInfo.InvariantCulture));
			}
		}

		/// <summary>
		/// Duplicates the style properties of the specified System.Web.UI.WebControls.Style object for the 
		/// current instance of the WebTools.UI.WebControls.AlertStyle class.
		/// </summary>
		/// <param name="s">A System.Web.UI.WebControls.Style object that represents the style settings to copy.</param>
		public override void CopyFrom(Style s)
		{
			if (s != null)
			{
				base.CopyFrom(s); 

				AlertStyle style = s as AlertStyle;
				if (style != null && !style.IsEmpty)
				{
					if (s.RegisteredCssClass.Length != 0)
					{
						if (style.IsPropSet(PROP_VPADDING))
						{
							base.ViewState.Remove("VerticalPadding");
							style.ClearProp(PROP_VPADDING);
						}
						if (style.IsPropSet(PROP_HPADDING))
						{
							base.ViewState.Remove("HorizontalPadding");
							style.ClearProp(PROP_HPADDING);
						}
					}
					else
					{
						if (style.IsPropSet(PROP_VPADDING))
						{
							this.VerticalPadding = style.VerticalPadding;
						}
						if (style.IsPropSet(PROP_HPADDING))
						{
							this.HorizontalPadding = style.HorizontalPadding;
						}
					}
					if (style.IsPropSet(PROP_HALIGN))
					{
						this.HorizontalAlign = style.HorizontalAlign;
					}

				}
			}
		}

		/// <summary>
		/// Combines the style settings of the specified System.Web.UI.WebControls.Style object with the 
		/// current instance of the WebTools.UI.WebControls.AlertStyle class.
		/// </summary>
		/// <param name="s">A System.Web.UI.WebControls.Style object that represents the style settings 
		/// to combine with the WebTools.UI.WebControls.AlertStyle object.</param>
		public override void MergeWith(Style s)
		{
			if (s != null)
			{
				if (this.IsEmpty)
				{
					this.CopyFrom(s);
				}
				else
				{
					base.MergeWith(s);
					AlertStyle style = s as AlertStyle;
					if ((style != null) && !style.IsEmpty)
					{
						if (s.RegisteredCssClass.Length == 0)
						{
							if (style.IsPropSet(PROP_VPADDING))
							{
								this.VerticalPadding = style.VerticalPadding;
							}
							if (style.IsPropSet(PROP_HPADDING))
							{
								this.HorizontalPadding = style.HorizontalPadding;
							}
						}
						if (style.IsPropSet(PROP_HALIGN))
						{
							this.HorizontalAlign = style.HorizontalAlign;
						}
					}
				}
			}
		}

		/// <summary>
		/// Removes any defined style settings from the WebTools.UI.WebControls.AlertStyle class.
		/// </summary>
		public override void Reset()
		{
			if (this.IsPropSet(PROP_VPADDING))
			{
				base.ViewState.Remove("VerticalPadding");
			}
			if (this.IsPropSet(PROP_HPADDING))
			{
				base.ViewState.Remove("HorizontalPadding");
			}
			if (this.IsPropSet(PROP_HALIGN))
			{
				base.ViewState.Remove("HorizontalAlign");
			}
			base.Reset();

		}

		private new void LoadViewState(object state)
		{
			Pair pair = state as Pair;
			if (pair != null)
			{
				base.LoadViewState(pair.First);
				_bits = (BitArray)pair.Second;
			}
		}

		/// <summary>
		/// Saves the control view state.
		/// </summary>
		/// <returns>An object representing the state to be saved.</returns>
		protected override object SaveViewState()
		{
			object obj = base.SaveViewState();
			Pair pair = new Pair();
			pair.First = obj;
			pair.Second = _bits;
			return pair;
		}

		/// <summary>
		/// Cause the control to save view state.
		/// </summary>
		protected override void TrackViewState()
		{
			base.TrackViewState();
			_marked = true;
		}
		#endregion

		#region IStateManager Members

		bool IStateManager.IsTrackingViewState
		{
			get { return _marked; }
		}

		void IStateManager.LoadViewState(object state)
		{
			this.LoadViewState(state);
		}

		object IStateManager.SaveViewState()
		{
			return this.SaveViewState();
		}

		void IStateManager.TrackViewState()
		{
			this.TrackViewState();
		}

		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the amount of space to the left and right of the alert control's text.
		/// </summary>
		/// <value>The amount of space (in pixels) to the left and right of the alert control's text. The default is 0.</value>
		[DefaultValue(typeof(Unit), "")]
		[Description("Horizontal padding values for the region of the control.")]
		[Category("Layout")]
		[NotifyParentProperty(true)]
		public Unit HorizontalPadding
		{
			get
			{
				if (this.IsPropSet(PROP_HPADDING))
				{
					return (Unit)base.ViewState["HorizontalPadding"];
				}
				return Unit.Empty;
			}
			set
			{
				if ((value.Type == UnitType.Percentage) || (value.Value < 0))
				{
					throw new ArgumentOutOfRangeException("value");
				}
				base.ViewState["HorizontalPadding"] = value;
				this.SetProp(PROP_HPADDING);
			}
		}

		/// <summary>
		/// Gets or sets the amount of space above and below a alert control's text.
		/// </summary>
		/// <value>The amount of space (in pixels) above and below a alert control's text. The default is 0.</value>
		[NotifyParentProperty(true)]
		[DefaultValue(typeof(Unit), "")]
		[Category("Layout")]
		[Description("Vertical padding values for the region of the control.")]
		public Unit VerticalPadding
		{
			get
			{
				if (this.IsPropSet(PROP_VPADDING))
				{
					return (Unit)base.ViewState["VerticalPadding"];
				}
				return Unit.Empty;
			}
			set
			{
				if ((value.Type == UnitType.Percentage) || (value.Value < 0))
				{
					throw new ArgumentOutOfRangeException("value");
				}
				base.ViewState["VerticalPadding"] = value;
				this.SetProp(PROP_VPADDING);
			}
		}

		/// <summary>
		/// Gets or sets the horizontal alignment of the contents within a alert control.
		/// </summary>
		/// <value>One of the System.Web.UI.WebControls.HorizontalAlign values. The default 
		/// is System.Web.UI.WebControls.HorizontalAlign.NotSet.</value>
		[Category("Appearance")]
		[Description("The horizontal alignment of the specified section of the control.")]
		[DefaultValue("")]
		public HorizontalAlign HorizontalAlign
		{
			get
			{
				if (this.IsPropSet(PROP_HALIGN))
				{
					return (HorizontalAlign)base.ViewState["HorizontalAlign"];
				}
				return HorizontalAlign.NotSet;
			}
			set
			{
				if ((value < HorizontalAlign.NotSet) || (value > HorizontalAlign.Justify))
				{
					throw new ArgumentOutOfRangeException("value");
				}
				base.ViewState["HorizontalAlign"] = value;
				this.SetProp(PROP_HALIGN);
			}
		}
		#endregion
	}
}
